package com.snow.vpnclient.api;

import androidx.annotation.NonNull;
import androidx.core.util.Consumer;

import com.alibaba.fastjson.JSON;
import com.blankj.utilcode.util.ToastUtils;
import com.snow.vpnclient.data.LocalStorage;
import com.snow.vpnclient.common.ResponseModel;
import com.snow.vpnclient.util.Logger;
import com.snow.vpnclient.util.Notify;

import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * @author liufq
 * @since 2022-11-03 15:04:42
 */
public enum RetrofitHelper {

    INSTANCE;

    private UserService service;

    private static final int TIME_OUT = 30;

    RetrofitHelper() {
        getService();
    }

    public void getService() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .hostnameVerifier((hostname, session) -> true)
                .sslSocketFactory(new NetworkSSL(TrustManager.trustAllCert), TrustManager.trustAllCert)
                .addInterceptor(new DomainSwitchInterceptor())
                .connectTimeout(TIME_OUT, TimeUnit.SECONDS)
                .readTimeout(TIME_OUT, TimeUnit.SECONDS)
                .writeTimeout(TIME_OUT, TimeUnit.SECONDS)
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(LocalStorage.getClientApiServer())
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        service = retrofit.create(UserService.class);
    }

    public UserService build() {
        return service;
    }

    public <T> void http(Call<ResponseModel<T>> call, Consumer<T> consumer) {
        http(call, consumer, null);
    }

    public <T> void http(Call<ResponseModel<T>> call, Consumer<T> consumer, Notify error) {
        call.enqueue(new Callback<ResponseModel<T>>() {
            @Override
            public void onResponse(@NonNull Call<ResponseModel<T>> call, @NonNull Response<ResponseModel<T>> response) {
                Logger.d("请求接口：" + response.raw().request().url());
                ResponseModel<T> body = response.body();
                if (body == null) {
                    Logger.e("网络响应错误，URL=" + response.raw().request().url());
                    ToastUtils.showShort("请求失败");
                    return;
                }
                Logger.d("请求结果：" + JSON.toJSONString(body));
                if (body.getCode() != 200) {
                    ToastUtils.showShort(body.getMsg());
                    if (error != null) {
                        error.callback();
                    }
                } else {
                    T data = body.getData();
                    consumer.accept(data);
                }
            }

            @Override
            public void onFailure(@NonNull Call<ResponseModel<T>> call, @NonNull Throwable t) {
                Logger.e("请求失败", t);
                if (error != null) {
                    error.callback();
                }
            }
        });
    }

    public void httpString(Call<ResponseBody> call, Consumer<String> consumer) {
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) {
                Logger.d("请求接口：" + response.raw().request().url());
                try {
                    if (response.body() != null) {
                        String result = response.body().string();
                        Logger.d("请求结果：" + JSON.toJSONString(result));
                        consumer.accept(result);
                    }
                } catch (Exception e) {
                    Logger.e("请求失败", e);
                    ToastUtils.showShort("请求失败");
                }
            }

            @Override
            public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) {
                Logger.e("请求失败", t);
            }
        });
    }
}
